package generator 
{
	import Components.CauseDamage;
	import flash.display.Graphics;
	import flash.geom.Vector3D;
	import nl.jorisdormans.phantom2D.core.Phantom;
	import nl.jorisdormans.phantom2D.objects.GameObject;
	import nl.jorisdormans.phantom2D.objects.GameObjectComponent;
	import nl.jorisdormans.phantom2D.objects.IRenderable;
	import nl.jorisdormans.phantom2D.objects.shapes.BoundingBoxAA;
	import nl.jorisdormans.phantom2D.objects.shapes.BoundingPolygon;
	import nl.jorisdormans.phantom2D.objects.Tile;
	import nl.jorisdormans.phantom2D.objects.TiledObjectLayer;
	import nl.jorisdormans.phantom2D.util.MathUtil;
	/**
	 * ...
	 * @author Joris Dormans
	 */
	public class Cell extends GameObjectComponent implements IRenderable
	{
		/**
		 * Message to change the tile type, expects data: {type:int};
		 */
		public static var M_SET_TYPE:String = "setType";
		public var life:Number;
		private var _type:int;
		private var _nextType:int;
		private var tiledObjectLayer:TiledObjectLayer;
		private var owner : GameObject;
		
		public function Cell(type:int) 
		{
			this.type = type;
			this.nextType = type;
			this.life = 0;
			
		}
		
		override public function onInitialize():void 
		{
			super.onInitialize();
			tiledObjectLayer = gameObject.objectLayer as TiledObjectLayer;
			if (!tiledObjectLayer) {
				throw new Error("GameObject with Cell component should to be added to a TiledObjectLayer");
			}
		}
		
		override public function handleMessage(message:String, data:Object = null):int 
		{
			switch (message) {
				case M_SET_TYPE:
					type = data.type;
					return Phantom.MESSAGE_HANDLED;
			}
			return super.handleMessage(message, data);
		}
		
		public function applyNextType():void {
			type = nextType;
		}
		
		/* INTERFACE nl.jorisdormans.phantom2D.objects.IRenderable */
		
		public function render(graphics:Graphics, x:Number, y:Number, angle:Number = 0, zoom:Number = 1):void 
		{
			var color:uint;
			switch (type) {
				default:	
				case 0:
					color = 0xffffff;
					break;
				case 1:
				case 2:
				case 3:
				case 4:
				case 5:
					color = 0x8888ff;
					break;
				case 7:
					color = 0x0000ff;
					break;
			}
			
			graphics.beginFill(color);
			
			var ts:Number = tiledObjectLayer.tileSize;
			var hs:Number = ts * 0.5;
			
			switch (type) {
				default:
				case 0:
					break;
				case 7:
				case 1:
					graphics.drawRect(x - hs, y - hs, ts, ts);
					break;
				case 2:
					graphics.moveTo(x - hs, y - hs);
					graphics.lineTo(x + hs, y + hs);
					graphics.lineTo(x - hs, y + hs);
					graphics.lineTo(x - hs, y - hs);
					break;
				case 3:
					graphics.moveTo(x - hs, y - hs);
					graphics.lineTo(x + hs, y - hs);
					graphics.lineTo(x - hs, y + hs);
					graphics.lineTo(x - hs, y - hs);
					break;
				case 4:
					graphics.moveTo(x - hs, y - hs);
					graphics.lineTo(x + hs, y - hs);
					graphics.lineTo(x + hs, y + hs);
					graphics.lineTo(x - hs, y - hs);
					break;
				case 5:
					graphics.moveTo(x - hs, y + hs);
					graphics.lineTo(x + hs, y - hs);
					graphics.lineTo(x + hs, y + hs);
					graphics.lineTo(x - hs, y + hs);
					break;
				case 6:
					graphics.drawCircle(x, y, hs * (MathUtil.clamp(life/20+0.5, 0, 1)));
					break;
			}
			
			graphics.endFill();
		}
		
		public function generateObject():void {
			var ts:Number = tiledObjectLayer.tileSize;
			var hs:Number = ts * 0.5;
			
			switch (type) {
				default:
				case 0:
					gameObject.destroyed = true;
					gameObject.addComponent(new CauseDamage(owner));
					break;
				case 7:
					gameObject.addComponent(new CauseDamage(owner));
					break;
				case 1:
					gameObject.addComponent(new BoundingBoxAA(new Vector3D(ts, ts)));
					gameObject.addComponent(new CauseDamage(owner));
					break;
				case 2:
					gameObject.addComponent(new BoundingPolygon(new Vector3D( -hs, -hs), new Vector3D(hs, hs), new Vector3D( -hs, hs)));
					gameObject.addComponent(new CauseDamage(owner));
					break;
				case 3:
					gameObject.addComponent(new BoundingPolygon(new Vector3D( -hs, -hs), new Vector3D(hs, -hs), new Vector3D( -hs, hs)));
					gameObject.addComponent(new CauseDamage(owner));
					break;
				case 4:
					gameObject.addComponent(new BoundingPolygon(new Vector3D( -hs, -hs), new Vector3D(hs, -hs), new Vector3D(hs, hs)));
					gameObject.addComponent(new CauseDamage(owner));
					break;
				case 5:
					gameObject.addComponent(new BoundingPolygon(new Vector3D( -hs, hs), new Vector3D(hs, -hs), new Vector3D(hs, hs)));
					gameObject.addComponent(new CauseDamage(owner));
					break;
					
			}
		}
		
		public function get type():int 
		{
			return _type;
		}
		
		public function set type(value:int):void 
		{
			_type = value;
			_nextType = value;
			
		}
		
		public function get nextType():int 
		{
			return _nextType;
		}
		
		public function set nextType(value:int):void 
		{
			_nextType = value;
		}
		
		public function get tile():Tile {
			return gameObject.tile;
		}
		
		public static function cellOnTile(tile:Tile, type:int):Boolean {
			if (!tile) return false;
			for (var i:int = 0; i < tile.objects.length; i++) {
				var cell:Cell = tile.objects[i].getComponentByClass(Cell) as Cell;
				if (cell) return (cell.type == type);
			}
			return false;
		}
		
		public function countNeighbors(type:int, countDiagonal:Boolean = true):int {
			var tile:Tile = gameObject.tile;
			if (!tile) return 0;
			var r:int = 0;
			if (tile.up && cellOnTile(tile.up, type)) r++;
			if (tile.down && cellOnTile(tile.down, type)) r++;
			if (tile.left && cellOnTile(tile.left, type)) r++;
			if (tile.right && cellOnTile(tile.right, type)) r++;
			if (countDiagonal) {
				if (tile.up && tile.up.left && cellOnTile(tile.up.left, type)) r++;
				if (tile.up && tile.up.right && cellOnTile(tile.up.right, type)) r++;
				if (tile.down && tile.down.left && cellOnTile(tile.down.left, type)) r++;
				if (tile.down && tile.down.right && cellOnTile(tile.down.right, type)) r++;
			}
			return r;
		}

		
		
		
		
		
		
	}

}